<template>
    <div id="tabs-view-container" class="tabs-view-container">
        <el-tabs v-model="activeName" type="border-card" @tab-click="handleTabClick" @tab-remove="handleTabRemove" @contextmenu.prevent.native="openContextMenu($event)">
            <el-tab-pane v-for="view in visitedViews" :closable="!isAffix(view)" :key="view.path" :label="generateTitle(view.title)"
                :name="view.path">
            </el-tab-pane>
            <ul v-show="contextMenuVisible" :style="{ left: left + 'px', top: top + 'px' }" class="contextmenu">
                <li @click="refreshSelectedTab(selectedTab)">
                    <span class="contextmenu-icon el-icon-refresh"></span>
                    刷新
                </li>
                <li v-if="!isAffix(selectedTab)" @click="closeSelectedTab(selectedTab)">
                    <span class="contextmenu-icon el-icon-close"></span>
                    关闭
                </li>
                <li @click="closeOthersTabs">
                    <span class="contextmenu-icon"></span>
                    关闭其他
                </li>
                <li @click="closeAllTabs">
                    <span class="contextmenu-icon el-icon-document-delete"></span>
                    关闭所有
                </li>
            </ul>
        </el-tabs>
    </div>
</template>
  
<script>
import { mapActions, mapState } from 'pinia';
import { useTabsViewStore } from "../../../store";
import { generateTitle } from "@/utils/i18n";
export default {
    data() {
        return {
            activeName: this.$route.path,
            contextMenuVisible: false,
            top: 0,
            left: 0,
            selectedTab: {},
            isAdded: false
        }
    },
    computed: {
        ...mapState(useTabsViewStore, ["visitedViews"]),
        routes() {
            return this.$router.options.routes
        },
    },
    watch: {
        $route(route) {
            let activeName = route.path
            this.addTabs()
            if(route.matched[0].path.indexOf(":child*")!=-1){
                activeName = route.matched[0].path.replace(/\:child\*/, "")
            }
            this.activeName = activeName;
        },
        contextMenuVisible(value) {
            if (value) {
                document.body.addEventListener('click', this.closeMenu)
            } else {
                document.body.removeEventListener('click', this.closeMenu)
            }
        }
    },
    mounted() {
        this.initTags()
        this.addTabs()
        console.log(this.selectedTab);
    },
    methods: {
        ...mapActions(useTabsViewStore, ['addVisitedView', 'delVisitedView']),
        isActive(route) {
            let activePath = this.$route.path
            if(this.$route.matched[0].path.indexOf(":child*")!=-1){
                activePath = this.$route.matched[0].path.replace(/\:child\*/, "")
            }
            return route.path === activePath;
        },

        isAffix(tag) {
            return tag.meta && tag.meta.affix
        },
        handleTabClick(tab) {
            const view = this.visitedViews[tab.index]
            this.$router.push(view.fullPath)
        },
        filterAffixTags(routes, basePath = '/') {
            let tabs = []
            routes.forEach(route => {
                if (route.meta && route.meta.affix) {
                    const tagPath = this.combineURL(basePath,route.path)
                    tabs.push({
                        fullPath: tagPath,
                        path: tagPath,
                        name: route.name,
                        meta: { ...route.meta }
                    })
                }
                if (route.children) {
                    const tempTags = this.filterAffixTags(route.children, route.path)
                    if (tempTags.length >= 1) {
                        tabs = [...tabs, ...tempTags]
                    }
                }
            })
            return tabs
        },
        initTags() {
            const affixTags = this.affixTags = this.filterAffixTags(this.routes)
            for (const tag of affixTags) {
                // Must have tag name
                if (tag.name) {
                    this.addVisitedView(tag)
                }
            }
        },
        addTabs() {
            const { name } = this.$route
            if (name) {
                this.addVisitedView(this.$route)
            }
            return false
        },
        handleTabRemove(path) {
            const view = this.visitedViews.find(v => v.path == path)
            this.delVisitedView(view)
            if (this.isActive(view)) {
                this.toLastView(this.visitedViews, view)
            }
        },
        toLastView(visitedViews, view) {
            const latestView = visitedViews.slice(-1)[0]
            if (latestView) {
                this.$router.push(latestView.fullPath)
            } else {
                // now the default is to redirect to the home page if there is no tabs-view,
                // you can adjust it according to your needs.
                if (view.name === 'Dashboard') {
                    // to reload home page
                    this.$router.replace({ path: '/redirect' + view.fullPath })
                } else {
                    this.$router.push('/')
                }
            }
        },
        openContextMenu(event){
            if (event.srcElement.id || (event.target.className==="el-icon-close")) {
                const offsetLeft = this.$el.getBoundingClientRect().left;
                const offsetTop = this.$el.getBoundingClientRect().top;
                const offsetWidth = this.$el.offsetWidth // container width
                const left = event.clientX - offsetLeft + 15 // 15: margin right
                const top = offsetTop - event.clientY - 5; // 5: margin top
                let currentContextTabPath = (event.srcElement.id || event.target.parentElement.id) .split("-")[1];
                if (left > offsetWidth) {
                    this.left = offsetWidth
                } else {
                    this.left = left
                }
                this.top = top;
                this.contextMenuVisible = true;
                this.selectedTab = this.visitedViews.find(view=>view.path === currentContextTabPath)
            }
        },
        closeMenu(){
            this.contextMenuVisible = false
        },
        refreshSelectedTab(view) {
            const { fullPath } = view
            this.$nextTick(() => {
                this.$router.replace({
                    path: '/redirect' + fullPath
                })
            })
        },
        closeSelectedTab(view) {
            this.delVisitedView(view)
            if (this.isActive(view)) {
                this.toLastView(this.visitedViews, view)
            }
        },
        closeOthersTabs() {
            this.$router.push(this.selectedTab)
            this.visitedViews.forEach(view => {
                if (this.affixTags.some(tag => tag.path === view.path)) {
                    return
                }
                if (view.path !== this.selectedTab.path) {
                    this.$nextTick(()=>{
                        this.delVisitedView(view)
                    })
                }
            })
        },
        closeAllTabs() {
            this.visitedViews.forEach(view => {
                if (this.affixTags.some(tag => tag.path === view.path)) {
                    return
                }
                this.$nextTick(()=>{
                    this.delVisitedView(view)
                    this.toLastView(this.visitedViews, view)
                })
            })

        },
        combineURL(baseURL, relativeURL) {
            return relativeURL ? baseURL.replace(/\/+$/, '') + '/' + relativeURL.replace(/^\/+/, '') : baseURL
        },
        generateTitle
    }
}
</script>
  
<style lang="scss" scoped>
.tabs-view-container {
    width: 100%;
    ::v-deep .el-tabs {
        &.el-tabs--border-card{
            border: none;
            box-shadow: none;
        }
        .el-tabs__header {
            background: $--color-white;
            .el-tabs__nav {
                border: none;
                .el-tabs__item {
                    transition: none;
                    &.is-active {
                        background: $--color-active-background;
                        border-left: none;
                        border-right: none;
                        box-shadow: 12px 12px 0 0 $--color-active-background, -12px 12px 0 0 $--color-active-background;
                        &:not(:first-child)::before {
                            content: '';
                            position: absolute;
                            top: 0;
                            left: -12px;
                            bottom: 0;
                            width: 12px;
                            background: $--color-white;
                            border-radius: 0 0 12px 0;
                        }
                        &::after {
                            content: '';
                            position: absolute;
                            top: 0;
                            right: -12px;
                            bottom: 0;
                            width: 12px;
                            background: $--color-white;
                            border-radius: 0 0 0 12px;
                        }
                    }

                    .el-icon-close {
                        width: 14px !important;
                    }
                }
                .el-tabs__item:not(:first-child) {
                    margin-left: 5px;
                }
            }
        }
        .el-tabs__content {
            overflow: unset;
            padding: 0;
        }
    }

    .contextmenu {
        margin: 0;
        background: $--color-white;
        z-index: 3000;
        position: absolute;
        list-style-type: none;
        padding: 5px 0;
        border-radius: 4px;
        font-size: 12px;
        font-weight: 400;
        color: #333;
        box-shadow: 2px 2px 3px 0 rgba(0, 0, 0, .3);

        li {
            margin: 0;
            padding: 7px 16px;
            cursor: pointer;
            text-align: left;
            .contextmenu-icon {
                display: inline-block;
                width: 14px;
                height: 14px;
            }
            &:hover {
                background: $--color-hover-background;
            }
        }
    }
}
</style>
